<?php
/**
 * RESPONSE 路由
 *
 * @category 
 * @package 
 * @author chenping<chenping@shopex.cn>
 * @version $Id: Z
 */
class erpapi_router_responsetest
{
    /**
     * 渠道节点
     *
     * @var string
     **/
    private $__node_id;

    /**
     * 接口名，如:wms.delivery.status_update
     *
     * @var string
     **/
    private $__api_name;

    /**
     * 渠道ID
     *
     * @var string
     **/
    private $__channel_id;

    public function set_node_id($node_id)
    {
        $this->__node_id = $node_id;
        return $this;
    }

    public function set_channel_id($channel_id)
    {
        $this->__channel_id = $channel_id;
        return $this;
    }

    public function set_api_name($api_name)
    {
        $this->__api_name = $api_name;
        return $this;
    }

    private function _parse_api_name()
    {
        list($channel_type, $business, $method) = explode('.',$this->__api_name);
        if ($channel_type == 'ome') $channel_type = 'shop';

        return array($channel_type,$business,$method);
    }

    public function dispatch($params,$sign_check=false)
    {

                
        list($usec, $sec) = explode(" ", microtime());
        $this->__start_time = $usec + $sec;

        try {
            // 节点和ID都不存在，抛出异常
            if (!$this->__node_id && !$this->__channel_id) throw new Exception("节点参数必填");         

            // 接口名不存在抛出异常
            if (!$this->__api_name) throw new Exception("接口名称必填");

            list($channel_type, $business, $method) = $this->_parse_api_name();
           
            // 实例化渠道类
            $channel_name = 'erpapi_channel_' . $channel_type;
            $channel_class = kernel::single($channel_name);

            if (!$channel_class instanceof erpapi_channel_abstract) throw new Exception("{$channel_name} not instanceof erpapi_channel_abstract");

            $channelRs = $channel_class->init($this->__node_id, $this->__channel_id);
            if (!$channelRs) throw new Exception("节点不存在");
            $adapter  = $channel_class->get_adapter();
            $platform = $channel_class->get_platform();
            $ver      = $channel_class->get_ver();

            // 配置文件
            if (in_array($adapter,array('matrix','openapi','prism')) && $sign_check) {
                // 默认
                $config_class = kernel::single('erpapi_'.$channel_type.'_config');

                // 如果有自身配置
                try {
                    if (class_exists('erpapi_'.$channel_type.'_'.$adapter.'_'.$platform.'_config')) {
                        $config_class = kernel::single('erpapi_'.$channel_type.'_'.$adapter.'_'.$platform.'_config');
                    }
                } catch (Exception $e) {
                    try {
                        if (class_exists('erpapi_'.$channel_type.'_'.$adapter)) {
                            $config_class = kernel::single('erpapi_'.$channel_type.'_'.$adapter.'_config');
                        }
                    } catch (Exception $e) {
                        
                    }
                }

                $config_class->init($channel_class);

                // 签名
                $sign = $params['sign']; unset($params['sign']);                
                $erp_sign = $config_class->gen_sign($params);

                if ($sign != $erp_sign) throw new Exception("签名错误");   
                

                if ($sign_check) return true;
            }

            // 默认数据转换类
            $object_class = $this->_get_object_class($adapter,$platform,$ver,$params);

            
            $object_class->init($channel_class);
           if(method_exists($object_class, $method)) {
                // 数据转成标准格式
                $convert_params = $object_class->{$method}($params);
            } else {
                throw new Exception(sprintf('The required method "%s" does not exist for %s',$method,get_class($object_class)));
            }

            $title = $object_class->__apilog['title'];
            $original_bn = $object_class->__apilog['original_bn'];
            $convert_result = $object_class->__apilog['result'];
            if (!$convert_params) {
                $this->_write_log($title,$original_bn,'fail',$params,$convert_params,$convert_result);
                return array('rsp'=>'fail','msg'=>$convert_result['msg'],'msg_code'=>'','data'=>$convert_result['data']);
            }

            // 数据验证
            try {
                $params_name = 'erpapi_'.$channel_type.'_response_params_'.$business;
                if (class_exists($params_name)) {
                    $valid = kernel::single($params_name)->check($convert_params,$method);

                    if ($valid['rsp'] != 'succ') {
                        
                        $this->_write_log($title,$original_bn,'fail',$params,$convert_params,$valid);

                        return array('rsp'=>'fail','msg'=>$valid['msg'],'msg_code'=>'','data'=>$convert_result['data']);
                    }
                }

            } catch (Exception $e) {
print_r($e);                
            }

echo 'erpapi_'.$channel_type.'_response_process_'.$business;
            // 最终的处理
            $result = kernel::single('erpapi_'.$channel_type.'_response_process_'.$business)->{$method}($convert_params);
           
var_dump($result);
                 
            $status  = ($result['rsp']=='succ' || $result['rsp']=='success') ? 'success' : 'fail';
            $this->_write_log($title,$original_bn,$status,$params,$convert_params,$result);

            if ($result['rsp'] != 'succ' && $result['rsp'] != 'success') {
                $apiParms = $result['data'];
               
                $result['data'] = $convert_result['data'];
                //放入失败队列处理
                $errorCode = kernel::single('erpapi_errcode')->getErrcode($channel_type);//错误码

                if($errorCode && (in_array($result['res'],array_keys($errorCode)) || in_array($result['msg_code'],array_keys($errorCode)))){
                     if(!$apiParms['obj_type']){
                        $apiParms['obj_type'] = $errorCode[$result['msg_code']]['obj_type'];
                    }

                    $failApiModel = app::get('erpapi')->model('api_fail');

                    $failApiModel->publish_api_fail($this->__api_name,$apiParms,$result);
                }
                return $result;
            }

            return $result['data'] ? $result['data'] : $convert_result['data'];
        } catch (Exception $e) {
            $result['msg'] = $e->getMessage().'('.$e->getTraceAsString().')';
            $this->_write_log('错误异常','response-exception','fail',$params,array(),$result);

            return array('rsp'=>'fail','msg'=>$e->getMessage(),'msg_code'=>'','data'=>null);
        }
    }

    /**
     * 获取处理类
     *
     * @return void
     * @author 
     **/
    private function _get_object_class($adapter,$platform,$ver,$params)
    {
        list($channel_type, $business, $method) = $this->_parse_api_name();

        $default_object_name = 'erpapi_'.$channel_type.'_response_'.$business;

        $object_name_arr = array('erpapi',$channel_type,$adapter,$platform,'response',$business);

        $object_name = implode('_',array_filter($object_name_arr));
        try {
            if (class_exists($object_name)) {
                $object_class = kernel::single($object_name);

                if (!is_subclass_of($object_class, $default_object_name))  throw new Exception("{$object_name} is a subclass of {$default_object_name}");
            }
        } catch (Exception $e) {
            
        }

        if (!is_object($object_class) && false !== strpos($platform, 'shopex_')) {
            $parentPlatForm = 'shopex';
            
            // 自带处理类
            $object_name_arr = array('erpapi', $channel_type, $adapter, $parentPlatForm, 'response', $business);
            $object_name = implode('_', array_filter($object_name_arr));
            try {
                if (class_exists($object_name)) {
                    $object_class = kernel::single($object_name);

                    if (!is_subclass_of($object_class, $default_object_name)) throw new Exception("{$object_name} is a subclass of {$default_object_name}");
                }
            } catch (Exception $e) {

            }
        }

        // 取默认
        if (!is_object($object_class)) {
            $object_class = kernel::single($default_object_name);
        }

        // 对象内业务流转
        if (method_exists($object_class, 'business_flow')) {
            $bsObjClass = $object_class->business_flow($params);

            if (is_object($bsObjClass)) return $bsObjClass;
        }

        return $object_class;
    }


    /**
     * 日志
     *
     * @return void
     * @author 
     **/
    private function _write_log($title,$original_bn,$status='succ',$params=array(),$convert_params=array(),$result=array())
    {
        if ($this->__concurrent_key) {
            cachecore::store($this->__concurrent_key,'',1);
        }

        // 写日志
        $apilogModel = app::get('ome')->model('api_log');
        $log_id = $apilogModel->gen_id();

        if ($params['task'] && $result['rsp']=='succ') $apilogModel->set_repeat($params['task'],$log_id);

        $msg = '接收参数：'.var_export($params,true).'<hr/>转换后参数：'.var_export($convert_params,true).'<hr/>返回结果：'.var_export($result,true);
        $logsdf = array(
            'log_id'        => $log_id,
            'task_name'     => $title,
            'status'        => $status,
            'worker'        => '',
            'params'        => '',
            'msg'           => $msg,
            'log_type'      => '',
            'api_type'      => 'response',
            'memo'          => '',
            'original_bn'   => $original_bn,
            'createtime'    => time(),
            'last_modified' => time(),
        );

        $apilogModel->insert($logsdf);

        
    }
}
